// Copyright 2016-2019 Proyectos y Sistemas de Mantenimiento SL (eProsima).
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ------------------------------------------------------------------
// Modification history:
// feature: Code style modification
// ------------------------------------------------------------------

#ifndef _EDDS_ENTITYRTPS_COMMON_GUIDPREFIX_T_HPP_
#define _EDDS_ENTITYRTPS_COMMON_GUIDPREFIX_T_HPP_

#include <ertps/ertps_dll.h>
#include <edds/rtps/common/Types.h>

#include <cstdint>
#include <cstring>
#include <sstream>
#include <iomanip>

#include <deps/common/GuidPrefix_t.hpp>

namespace evbs {
namespace ertps {
namespace rtps {
#if 0
//!@brief Structure GuidPrefix_t, Guid Prefix of GUID_t.
//!@ingroup COMMON_MODULE
struct RTPS_DllAPI GuidPrefix_t {
    static constexpr uint32_t size = 12U;
    octet value[size];

    //! Default constructor. Set the Guid prefix to 0.
    GuidPrefix_t() { (void)memset(value, 0, size); }

    static GuidPrefix_t unknown() { return GuidPrefix_t(); }

#ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC

    /**
     * Guid prefix comparison operator
     * @param prefix guid prefix to compare
     * @return True if the guid prefixes are equal
     */
    bool operator==(const GuidPrefix_t& prefix) const {
        return (memcmp(value, prefix.value, size) == 0);
    }

    /**
     * Guid prefix comparison operator
     * @param prefix Second guid prefix to compare
     * @return True if the guid prefixes are not equal
     */
    bool operator!=(const GuidPrefix_t& prefix) const {
        return (memcmp(value, prefix.value, size) != 0);
    }

    /**
     * Guid prefix minor operator
     * @param prefix Second guid prefix to compare
     * @return True if prefix is higher than this
     */
    bool operator<(const GuidPrefix_t& prefix) const {
        return std::memcmp(value, prefix.value, size) < 0;
    }

    /**
     * Guid Prefix compare static method.
     *
     * @param prefix1 First guid prefix to compare
     * @param prefix2 Second guid prefix to compare
     *
     * @return 0 if \c prefix1 is equal to \c prefix2 .
     * @return < 0 if \c prefix1 is lower than \c prefix2 .
     * @return > 0 if \c prefix1 is higher than \c prefix2 .
     */
    static int cmp(const GuidPrefix_t& prefix1, const GuidPrefix_t& prefix2) {
        return std::memcmp(prefix1.value, prefix2.value, size);
    }

#endif  // ifndef DOXYGEN_SHOULD_SKIP_THIS_PUBLIC
};

const GuidPrefix_t c_GuidPrefix_Unknown;

inline std::ostream& operator<<(std::ostream& output, const GuidPrefix_t& guiP) {
    output << std::hex;
    char old_fill = output.fill('0');
    for (uint8_t i = 0U; i < 11U; ++i) {
        output << std::setw(2) << (int)guiP.value[i] << ".";
    }
    output << std::setw(2) << (int)guiP.value[11];
    (void)output.fill(old_fill);
    return output << std::dec;
}

inline std::istream& operator>>(std::istream& input, GuidPrefix_t& guiP) {
    std::istream::sentry s(input);

    if (s) {
        char point;
        unsigned short hex;
        std::ios_base::iostate excp_mask = input.exceptions();

        try {
            input.exceptions(excp_mask | std::ios_base::failbit | std::ios_base::badbit);
            input >> std::hex >> hex;

            if (hex > 255U) {
                input.setstate(std::ios_base::failbit);
            }

            guiP.value[0] = static_cast<octet>(hex);

            for (int i = 1; i < 12; ++i) {
                input >> point >> hex;
                if ((point != '.') || (hex > 255U)) {
                    input.setstate(std::ios_base::failbit);
                }
                guiP.value[i] = static_cast<octet>(hex);
            }

            input >> std::dec;
        } catch (std::ios_base::failure&) {
            guiP = GuidPrefix_t::unknown();
        }

        input.exceptions(excp_mask);
    }

    return input;
}

#endif
using GuidPrefix_t = vbsutil::xmlparser::GuidPrefix_t;
using vbsutil::xmlparser::c_GuidPrefix_Unknown;

}  // namespace rtps
}  // namespace ertps
}  // namespace evbs

#endif /* _EDDS_ENTITYRTPS_COMMON_GUIDPREFIX_T_HPP_ */
